import { _decorator, AudioClip, AudioSource, Component, Node } from 'cc';
import GameEventMgr, { GameEvent } from './GameEventMgr';
const { ccclass, property } = _decorator;

@ccclass('SoundManager')
export class SoundManager {

    private static _instance: SoundManager = null;
    static get Instance() {
        if (SoundManager._instance == null) {
            SoundManager._instance = new SoundManager();
        }

        return SoundManager._instance;
    }

    musicSources: AudioSource[] = [];
    effectSources: AudioSource[] = [];

    baseMusicMap: Map<string, AudioClip> = new Map();

    baseEffectMap: Map<string, AudioClip> = new Map();

    private _globalVolume: number = 1.0;

    init() {
        // 初始化音量
        this.updateAllAudioSourcesVolume();
        GameEventMgr.Register(this, GameEvent.AudioClipEnded, this.onAudioClipEndedHandle.bind(this));
    }

    setVolume(volume: number) {
        this._globalVolume = volume;
        this.updateAllAudioSourcesVolume();
    }

    getVolume(): number {
        return this._globalVolume;
    }

    private updateAllAudioSourcesVolume() {
        this.musicSources.forEach(audioSource => {
            audioSource.volume = this._globalVolume;
        });
        this.effectSources.forEach(audioSource => {
            audioSource.volume = this._globalVolume;
        });
    }

    addAudioSource(audioSource: AudioSource, isMusic = false) {
        if (isMusic) {
            let index = this.musicSources.indexOf(audioSource);
            if (index != -1) {
                this.musicSources.push(audioSource);
            }
        }
        else {
            let index = this.effectSources.indexOf(audioSource);
            if (index != -1) {
                this.effectSources.push(audioSource);
            }
        }
        audioSource.volume = this._globalVolume;
    }

    removeAudioSource(audioSource: AudioSource) {
        let index = this.musicSources.indexOf(audioSource);
        if (index > -1) {
            this.musicSources.splice(index, 1);
        }
        index = this.effectSources.indexOf(audioSource);
        if (index > -1) {
            this.effectSources.splice(index, 1);
        }
    }

    stopMusic() {
        this.musicSources.forEach(audioSource => {
            audioSource.stop();
        });
    }

    stopEffect() {
        this.effectSources.forEach(audioSource => {
            audioSource.stop();
        });
    }

    playAudio(source: AudioSource, clipName: string, isMusic = false) {
        let volume = this._globalVolume;
        SoundManager.Instance.addAudioSource(source, isMusic);
        if (isMusic) {
            source.clip = this.baseMusicMap.get(clipName);
        }
        else {
            //同时播放的音效越多，音量越小
            volume = 1 / this.effectSources.length * this._globalVolume;
            source.clip = this.baseEffectMap.get(clipName);
        }
        if (!source.clip) {
            GameEventMgr.Dispatch(GameEvent.LogGameMessage, "没有这个音效" + clipName);
            console.log("没有这个音效" + clipName);
        }
        source.volume = volume;
        source.play();
        source.node.on(Node.EventType.NODE_DESTROYED, () => {
            GameEventMgr.Dispatch(GameEvent.AudioClipEnded, source);
        });
        source.node.once('ended', () => {
            GameEventMgr.Dispatch(GameEvent.AudioClipEnded, source);
        }, this);
    }

    onAudioClipEndedHandle(audioSource: AudioSource) {
        this.removeAudioSource(audioSource);

        if (audioSource.isValid) {
            console.log('销毁音效' + audioSource.clip.name)
            audioSource.destroy();
        }
    }
}


